package model;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import modeleIndexation.DocIndex;
import modeleIndexation.NoeudIndex;
import modeleIndexation.TermesIndex;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import Main.Mysql;

public class ParseXML extends DefaultHandler{
	Mysql bdd = Mysql.getInstance();
	private File repertoire; 
	private DocumentBuilderFactory dbf;
	private DocumentBuilder db;
	private XMLReader xmlReader;
	private String path = "./Collection/";
	private String stopListePath = "./stopliste.txt";
	private String currentFile = "";
	private List<DocIndex> listeDocIndex;
	private TermesIndex listeTermesIndex;
	private Stack<NoeudIndex> pileNoeud;		// mÃ©morise la rÃ©fÃ©rence du pÃ¨re
	private Stack<HashMap<String,Integer>> pileOrdreNoeuds; // mÃ©morise l'ordre du noeud courant
	private HashSet<String> hashStopListe;
	
	public ParseXML(){
		super();
		listeDocIndex = new ArrayList<DocIndex>();
		pileNoeud = new Stack<NoeudIndex>();
		pileOrdreNoeuds = new Stack<HashMap<String,Integer>>();
		hashStopListe = new HashSet<String>();
		repertoire = new File(path);
		listeTermesIndex = new TermesIndex();
		
		initStopListe();

		try {
			
			xmlReader = XMLReaderFactory.createXMLReader();
			xmlReader.setContentHandler(this);
			xmlReader.setErrorHandler(this);
			
		} catch (SAXException e) {
			e.printStackTrace();
		}
		
		System.out.println("Indexation...");
		parseXmlFile();
		System.out.println("\t-->terminée");
		
		/* Insertion dans la base de donnÃ©es */
		System.out.println("Insertion BDD...");
		bdd.supprimerTout ();
		long timeDeb = System.currentTimeMillis();
		toBdd ();
		listeTermesIndex.toBdd();
		long timeFin = System.currentTimeMillis();
		System.out.println("\t-->terminée ( temps : " + (timeFin - timeDeb)/1000 +" s)");
		
	}
	
	private void initStopListe(){
		InputStream ips;
		try {
			
			ips = new FileInputStream(stopListePath);
			InputStreamReader ipsr=new InputStreamReader(ips);
			BufferedReader br =new BufferedReader(ipsr);
			String ligne;
			while ((ligne=br.readLine())!=null){
				hashStopListe.add(ligne);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	
	private void parseXmlFile(){
		try {
			
			String [] listefichiers;
			listefichiers = repertoire.list();
			for(int i=0; i<listefichiers.length;i++){
				if(listefichiers[i].endsWith(".xml")==true){
					currentFile = listefichiers[i];
					FileReader xml = new FileReader(path+currentFile);
					xmlReader.parse(new InputSource(xml));
				}
			}
	
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			ioe.printStackTrace();
		}
	}
	



    ////////////////////////////////////////////////////////////////////
    // Event handlers.
    ////////////////////////////////////////////////////////////////////


    public void startDocument ()
    {
    	listeDocIndex.add(new DocIndex(currentFile));

    }


    public void endDocument ()
    {

    }

    public void startElement (String uri, String name,String qName, Attributes atts)
    {
    	NoeudIndex noeud;
    	if (pileNoeud.empty()) {
    		List<NoeudIndex> ln = listeDocIndex.get(listeDocIndex.size()-1).getListeNoeuds();
    		noeud = new NoeudIndex(qName,1);
    		ln.add(noeud);

    	} else {
    		NoeudIndex nd = pileNoeud.peek();
    		noeud = new NoeudIndex(qName, (pileOrdreNoeuds.peek().containsKey(qName))?(pileOrdreNoeuds.peek().get(qName)):1);
    		pileOrdreNoeuds.peek().put(qName, (pileOrdreNoeuds.peek().containsKey(qName))?(pileOrdreNoeuds.peek().get(qName)+1):1);
    		nd.addFils(noeud);

    	}
    	HashMap<String, Integer> toPush = new HashMap<String, Integer>();
    	toPush.put(qName,1);
    	pileOrdreNoeuds.push(toPush);
    	pileNoeud.push(noeud);

    }
    
    public void endElement (String uri, String name, String qName)
    {
    	pileOrdreNoeuds.pop();
    	pileNoeud.pop();

    }


    public void characters (char ch[], int start, int length)
    {
    	String maChaine = "";
    	for(int i = start ; i < start+length ; i++)
    		maChaine += ch[i];
    	
    	maChaine = replaceSpecialChar(maChaine);
    	maChaine = maChaine.toLowerCase();
    	
    	String REGEX = "[ 1234567890°{}$€%£*~@=^|#&§«»“”‹›<>„\"�…’'`_–,/.:;!?()\\-+*\n\t]+";
    	Pattern p = Pattern.compile(REGEX);
	    String[] items = p.split(maChaine);
	    for (int i = 0; i < items.length; i++) {
	    	
	    	if(!hashStopListe.contains(items[i]) && items[i].length() > 1 ) {
	    		String toInsert= (items[i].length() <= 7) ? items[i] : items[i].substring(0,7);
	    		listeTermesIndex.addTerme(toInsert, pileNoeud.peek(), i);
	    	}
	      
	    }
    }

    public void printTermes (int number) {
    	Set<String> s = listeTermesIndex.getTermes ();
    	for (int i=0; i< number; i++)
    		System.out.println(s.toArray()[i]);
    }
    
    public void toBdd () {
    	
    	/* InsÃ¨re les documents dans la bdd */
    	String request = "INSERT INTO Documents (nom) VALUES ";
    	for (int i=0; i<listeDocIndex.size();i++) {
    		request += ((i==0)?"":",") + "('" + this.listeDocIndex.get(i).getName() + "')";
    	}
    	request += ";";
		bdd.executeInsert(request);
		
		/* InsÃ¨re pour chaque document tous ses fils */
    	for (int i=0; i<listeDocIndex.size();i++) {
    		String queryID = "SELECT id FROM Documents WHERE nom ='" + this.listeDocIndex.get(i).getName() + "';";
    		int id = Integer.parseInt((String) bdd.getResultSet(bdd.executeSelect(queryID)).get(0).get(0));
    		
    		for (int k=0; k<listeDocIndex.get(i).getListeNoeuds().size();k++) {
        		listeDocIndex.get(i).getListeNoeuds().get(k).toBddfromDoc(id);
    		}
    	}	
    }
    
    public static String replaceSpecialChar(String maChaine){

    	maChaine = maChaine.replaceAll("ç", "c");
		maChaine = maChaine.replaceAll("é", "e");
		maChaine = maChaine.replaceAll("É", "E");
		maChaine = maChaine.replaceAll("è", "e");
		maChaine = maChaine.replaceAll("ê", "e");
		maChaine = maChaine.replaceAll("ê", "e");
		maChaine = maChaine.replaceAll("è", "e");
		maChaine = maChaine.replaceAll("ë", "e");
		maChaine = maChaine.replaceAll("à", "a");
		maChaine = maChaine.replaceAll("â", "a");
    	maChaine = maChaine.replaceAll("â", "a");
    	maChaine = maChaine.replaceAll("ä", "a");
    	maChaine = maChaine.replaceAll("œ", "oe");
    	maChaine = maChaine.replaceAll("æ", "ae");
    	maChaine = maChaine.replaceAll("ï", "i");
    	maChaine = maChaine.replaceAll("î", "i");
    	maChaine = maChaine.replaceAll("ü", "u");
    	maChaine = maChaine.replaceAll("û", "u");
    	maChaine = maChaine.replaceAll("ù", "u");
    	maChaine = maChaine.replaceAll("ö", "o");
    	maChaine = maChaine.replaceAll("ô", "o");
    	maChaine = maChaine.replaceAll("'", " ");
    	maChaine = maChaine.replaceAll("`", " ");
    	maChaine = maChaine.replaceAll("\\\\", " ");

    	return maChaine;
    }
}
